package com.example.monitor.service;

import com.example.monitor.Sleeper;
import com.example.monitor.controller.MonitorController;
import com.example.monitor.vo.Info;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * @author mqb
 * @date 2021/4/27 22:36
 */
@Service
@Slf4j
public class MonitorService {
    private volatile boolean stop;
    private volatile boolean starting;
    private Thread monitorThread;

    public void start() {
        synchronized (this) {
            log.info("该监控线程已启动？ [{}]", starting);
            if (starting) {
                return;
            }
            starting = true;
        }

        // 由于之前的 balking模式，以下代码只可能一个线程执行，所以无需互斥
        monitorThread = new Thread(() -> {
            while (!stop) {
                report();
                Sleeper.sleep(2);
            }

            // 这里的starting不在synchronized，可见性需要volatile保证
            log.info("监控线程已停止....");
            starting = false;
        });

        stop = false;
        log.info("监控线程已启动");
        monitorThread.start();
    }

    public void stop() {
        stop = true;
        monitorThread.interrupt();
    }

    private void report(){
        Info info = new Info();
        info.setTotal(Runtime.getRuntime().totalMemory());
        info.setFree(Runtime.getRuntime().freeMemory());
        info.setMax(Runtime.getRuntime().maxMemory());
        info.setTime(System.currentTimeMillis());
        MonitorController.QUEUE.offer(info);
    }
}
